/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.zxing.client.android.result;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.util.Log;

import com.google.zxing.R;
import com.google.zxing.client.result.CalendarParsedResult;
import com.google.zxing.client.result.ParsedResult;

import java.text.DateFormat;
import java.util.Date;

/**
 * Handles calendar entries encoded in QR Codes.
 *
 * @author dswitkin@google.com (Daniel Switkin)
 * @author Sean Owen
 */
public final class CalendarResultHandler extends ResultHandler {

    private static final String TAG = CalendarResultHandler.class.getSimpleName();

    private static final int[] buttons = {
            R.string.button_add_calendar
    };

    public CalendarResultHandler(Activity activity, ParsedResult result) {
        super(activity, result);
    }

    @Override
    public int getButtonCount() {
        return buttons.length;
    }

    @Override
    public int getButtonText(int index) {
        return buttons[index];
    }

    @Override
    public void handleButtonPress(int index) {
        if (index == 0) {
            CalendarParsedResult calendarResult = (CalendarParsedResult) getResult();

            String description = calendarResult.getDescription();
            String organizer = calendarResult.getOrganizer();
            if (organizer != null) { // No separate Intent key, put in description
                if (description == null) {
                    description = organizer;
                } else {
                    description = description + '\n' + organizer;
                }
            }

            addCalendarEvent(calendarResult.getSummary(),
                    calendarResult.getStart(),
                    calendarResult.isStartAllDay(),
                    calendarResult.getEnd(),
                    calendarResult.getLocation(),
                    description,
                    calendarResult.getAttendees());
        }
    }

    /**
     * Sends an intent to create a new calendar event by prepopulating the Add Event UI. Older
     * versions of the system have a bug where the event title will not be filled out.
     *
     * @param summary A description of the event
     * @param start   The start time
     * @param allDay  if true, event is considered to be all day starting from start time
     * @param end     The end time (optional)
     * @param location a text description of the event location
     * @param description a text description of the event itself
     * @param attendees attendees to invite
     */
    private void addCalendarEvent(String summary,
                                  Date start,
                                  boolean allDay,
                                  Date end,
                                  String location,
                                  String description,
                                  String[] attendees) {
        Intent intent = new Intent(Intent.ACTION_INSERT);
        intent.setType("vnd.android.cursor.item/event");
        long startMilliseconds = start.getTime();
        intent.putExtra("beginTime", startMilliseconds);
        if (allDay) {
            intent.putExtra("allDay", true);
        }
        long endMilliseconds;
        if (end == null) {
            if (allDay) {
                // + 1 day
                endMilliseconds = startMilliseconds + 24 * 60 * 60 * 1000;
            } else {
                endMilliseconds = startMilliseconds;
            }
        } else {
            endMilliseconds = end.getTime();
        }
        intent.putExtra("endTime", endMilliseconds);
        intent.putExtra("title", summary);
        intent.putExtra("eventLocation", location);
        intent.putExtra("description", description);
        if (attendees != null) {
            intent.putExtra(Intent.EXTRA_EMAIL, attendees);
            // Documentation says this is either a String[] or comma-separated String, which is right?
        }

        try {
            // Do this manually at first
            rawLaunchIntent(intent);
        } catch (ActivityNotFoundException anfe) {
            Log.w(TAG, "No calendar app available that responds to " + Intent.ACTION_INSERT);
            // For calendar apps that don't like "INSERT":
            intent.setAction(Intent.ACTION_EDIT);
            launchIntent(intent); // Fail here for real if nothing can handle it
        }
    }


    @Override
    public CharSequence getDisplayContents() {

        CalendarParsedResult calResult = (CalendarParsedResult) getResult();
        StringBuilder result = new StringBuilder(100);

        ParsedResult.maybeAppend(calResult.getSummary(), result);

        Date start = calResult.getStart();
        ParsedResult.maybeAppend(format(calResult.isStartAllDay(), start), result);

        Date end = calResult.getEnd();
        if (end != null) {
            if (calResult.isEndAllDay() && !start.equals(end)) {
                // Show only year/month/day
                // if it's all-day and this is the end date, it's exclusive, so show the user
                // that it ends on the day before to make more intuitive sense.
                // But don't do it if the event already (incorrectly?) specifies the same start/end
                end = new Date(end.getTime() - 24 * 60 * 60 * 1000);
            }
            ParsedResult.maybeAppend(format(calResult.isEndAllDay(), end), result);
        }

        ParsedResult.maybeAppend(calResult.getLocation(), result);
        ParsedResult.maybeAppend(calResult.getOrganizer(), result);
        ParsedResult.maybeAppend(calResult.getAttendees(), result);
        ParsedResult.maybeAppend(calResult.getDescription(), result);
        return result.toString();
    }

    private static String format(boolean allDay, Date date) {
        if (date == null) {
            return null;
        }
        DateFormat format = allDay
                ? DateFormat.getDateInstance(DateFormat.MEDIUM)
                : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
        return format.format(date);
    }

    @Override
    public int getDisplayTitle() {
        return R.string.result_calendar;
    }
}
